package entities;

import java.io.Serializable;
import java.util.Date;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;

import enums.MatchStatus;

@Entity
@Table(name="match")
@NamedQueries({
	@NamedQuery(name="getListMatchByFlagActivatedByTournament",query="SELECT match FROM Match AS match WHERE match.oneFlag = :flag AND match.tournament = :tournament"),
	@NamedQuery(name="getListMatchByFlagActivatedByTournamentAndByStatus",query="SELECT match FROM Match AS match WHERE match.oneFlag = :flag AND match.tournament = :tournament AND match.status = :status")
})
public class Match extends EntityMother implements Serializable, Comparable<Match> {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private long id;

	@OneToOne(fetch = FetchType.EAGER)
	private Team homeTeam;

	@OneToOne(fetch = FetchType.EAGER)
	private Team outsideTeam;

	@ManyToOne(fetch = FetchType.EAGER)
	private Referee referee;

	private int scoreHome;

	private int scoreOutside;

	@Temporal(TemporalType.DATE)
	private Date startDate;

	@OneToMany(mappedBy = "match", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
	private Set<Event> listEvent;

	@ManyToOne
	private Tournament tournament;

	private int roundNumber;

	private int matchNumber;

	@Enumerated(EnumType.STRING)
	private MatchStatus status;

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public Team getHomeTeam() {
		return homeTeam;
	}

	public void setHomeTeam(Team homeTeam) {
		this.homeTeam = homeTeam;
	}

	public Team getOutsideTeam() {
		return outsideTeam;
	}

	public void setOutsideTeam(Team outsideTeam) {
		this.outsideTeam = outsideTeam;
	}

	public Referee getReferee() {
		return referee;
	}

	public void setReferee(Referee referee) {
		this.referee = referee;
	}

	public int getScoreHome() {
		return scoreHome;
	}

	public void setScoreHome(int scoreHome) {
		this.scoreHome = scoreHome;
	}

	public int getScoreOutside() {
		return scoreOutside;
	}

	public void setScoreOutside(int scoreOutside) {
		this.scoreOutside = scoreOutside;
	}

	public Date getStartDate() {
		return startDate;
	}

	public void setStartDate(Date startDate) {
		this.startDate = startDate;
	}

	public Set<Event> getListEvent() {
		return listEvent;
	}

	public void setListEvent(Set<Event> listEvent) {
		this.listEvent = listEvent;
	}

	public Tournament getTournament() {
		return tournament;
	}

	public void setTournament(Tournament tournament) {
		this.tournament = tournament;
	}

	public int getRoundNumber() {
		return roundNumber;
	}

	public void setRoundNumber(int roundNumber) {
		this.roundNumber = roundNumber;
	}

	public int getMatchNumber() {
		return matchNumber;
	}

	public void setMatchNumber(int matchNumber) {
		this.matchNumber = matchNumber;
	}

	public MatchStatus getStatus() {
		return status;
	}

	public void setStatus(MatchStatus status) {
		this.status = status;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) return true;
		if (!(o instanceof Match)) return false;

		Match match = (Match) o;

		if (id != match.id) return false;
		if (scoreHome != match.scoreHome) return false;
		if (scoreOutside != match.scoreOutside) return false;
		if (homeTeam != null ? !homeTeam.equals(match.homeTeam) : match.homeTeam != null) return false;
		if (outsideTeam != null ? !outsideTeam.equals(match.outsideTeam) : match.outsideTeam != null) return false;
		if (referee != null ? !referee.equals(match.referee) : match.referee != null) return false;
		if (startDate != null ? !startDate.equals(match.startDate) : match.startDate != null) return false;

		return true;
	}

	@Override
	public int hashCode() {
		int result = (int) (id ^ (id >>> 32));
		result = 31 * result + (homeTeam != null ? homeTeam.hashCode() : 0);
		result = 31 * result + (outsideTeam != null ? outsideTeam.hashCode() : 0);
		result = 31 * result + (referee != null ? referee.hashCode() : 0);
		result = 31 * result + scoreHome;
		result = 31 * result + scoreOutside;
		result = 31 * result + (startDate != null ? startDate.hashCode() : 0);
		result = 31 * result + (tournament != null ? tournament.hashCode() : 0);
		result = 31 * result + roundNumber;
		result = 31 * result + matchNumber;
		return result;
	}

	@Override
	public int compareTo(Match o) {
		if(this.getRoundNumber() < o.getRoundNumber()){
			return -1;
		}else
			if(this.getRoundNumber() == o.getRoundNumber()){
				if(this.getMatchNumber() < o.getMatchNumber()){
					return -1;
				}else
					if(this.getMatchNumber() == o.getMatchNumber()){
						return 0;
					}else{
						return 1;
					}
			}else{
				return 1;
			}
	}
}
